package com.letoken.platform.app.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.letoken.platform.app.service.AppFundInfoService;
import com.letoken.platform.app.service.AppFundV2InfoService;
import com.letoken.platform.app.service.AppUserLampService;
import com.letoken.platform.app.service.AppUserWalletService;
import com.letoken.platform.pub.annotation.auth.NotAuthorization;
import com.letoken.platform.pub.constant.RedisKeyConstant;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenTokenTypeEnum;
import com.letoken.platform.pub.enums.TokenTransactionStatusEnum;
import com.letoken.platform.pub.enums.TokenTransactionTypeEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.req.PageData;
import com.letoken.platform.pub.req.PageReq;
import com.letoken.platform.pub.res.ApiResponse;
import com.letoken.platform.repo.admin.dao.AdminFundConfigMapper;
import com.letoken.platform.repo.admin.po.AdminFundConfig;
import com.letoken.platform.repo.app.dao.*;
import com.letoken.platform.repo.app.po.AppFundDetail;
import com.letoken.platform.repo.app.po.AppFundInfo;
import com.letoken.platform.repo.app.po.AppFundV2Detail;
import com.letoken.platform.repo.app.po.AppUserAssetsHistory;
import com.letoken.platform.repo.app.redis.RedisConfig;
import com.letoken.platform.repo.app.req.user.FundTransferReq;
import com.letoken.platform.repo.app.req.user.GetFundInfoList;
import com.letoken.platform.repo.app.res.assets.MingListRes;
import com.letoken.platform.repo.utlis.PageDataUtil;
import com.letoken.platform.repo.utlis.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/appFundCAPController")
@Slf4j
public class AppFundCAPController {

    @Resource
    AdminFundConfigMapper adminFundConfigMapper;

    @Resource
    AppUserWalletMapper appUserWalletMapper;

    @Autowired
    AppFundInfoService appFundInfoService;

    @Autowired
    AppUserWalletService appUserWalletService;
    @Resource
    AppFundInfoMapper appFundInfoMapper;


    @Autowired
    AppUserLampService appUserLampService;

    @Resource
    private RedisConfig redisConfig;


    private void checkout(FundTransferReq req){
        if ( req.getAmount().compareTo(BigDecimal.ONE) < 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_054);
        }
        //Integer balanceId = appBalanceWalletMapper.getIdByUserId(LetokenTokenTypeEnum.LET.getId(),req.getUserId());
        Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.CAP.getId(), req.getUserId());
        if (/*ObjectUtils.isEmpty(balanceId) ||*/ ObjectUtils.isEmpty(walletId)){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_051);
        }
        //req.setBalanceId(balanceId);
        req.setWalletId(walletId);
    }



    @GetMapping("/getFundConfig")
    public ApiResponse<Map<String,Object>> getFundConfig() {
        Map<String,Object> map = new HashMap<>();
        map.put("min",100);
        map.put("get",1);
        return ApiResponse.create(map);
    }


    @PostMapping("/transferInCAP")
    public ApiResponse transferInCAP(@Validated @RequestBody FundTransferReq req) {


        if (new BigDecimal(req.getAmount().intValue()).compareTo(req.getAmount())!=0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_055);
        }
        QueryWrapper<AdminFundConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",req.getFundId());
        AdminFundConfig adminFundConfig = adminFundConfigMapper.selectOne(queryWrapper);
        if(adminFundConfig == null || adminFundConfig.getMin().compareTo(req.getAmount())>0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_057);
        }
        req.setUserId(WebUtils.getUserId());
        req.setAdminFundConfig(adminFundConfig);
        checkout(req);
        BigDecimal bigDecimal = appFundInfoMapper.getFundAmountByType(req.getUserId(),req.getFundId());
        if(adminFundConfig.getMaxFund().compareTo(bigDecimal.add(req.getAmount()))<0){
            throw new ApiServiceException("发行失败,超过发行上限");
        }

        String key = RedisKeyConstant.UPDATE_FUND_INFO + req.getUserId();

        RedissonClient redissonClient = redisConfig.getRedisson();
        RLock rlock = redissonClient.getLock(key);
        try {
            rlock.lock(15, TimeUnit.SECONDS);
            appFundInfoService.transferInCAP(req);
        }finally {
            if (rlock != null && rlock.isHeldByCurrentThread()) {
                rlock.unlock();
            }
        }
        return ApiResponse.create();
    }

    @GetMapping("/updateFundInfoCAP")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse updateFundInfo(@RequestParam("fundId") Integer fundId) {
        // if (!list.contains(WebUtils.getUserId())) throw new ApiServiceException("赎回暂时关闭") ;
        QueryWrapper<AppFundInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",fundId).eq("user_id",WebUtils.getUserId()).eq("type",1).eq("state",1);
        AppFundInfo adminFundConfig = appFundInfoService.getOne(queryWrapper);
        if(adminFundConfig == null || adminFundConfig.getExpirationTime().compareTo(LocalDateTime.now()) > 0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_056);
        }
        adminFundConfig.setType(2);
        appFundInfoService.updateById(adminFundConfig);

        AppFundDetail appFundDetail = new AppFundDetail();
        appFundDetail.setUserId(adminFundConfig.getUserId());
        appFundDetail.setType(3);
        appFundDetail.setAmount(adminFundConfig.getFund());
        appFundDetail.setCreateTime(LocalDateTime.now());
        appFundDetail.setTitle(TokenTransactionTypeEnum.CAP_FUND_SELL.getText());
        appFundDetail.setRemark("-");
        appFundDetail.insert();

        AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
        assetHistory.setUserId(WebUtils.getUserId());
        assetHistory.setType(TokenTransactionTypeEnum.CAP_FUND_SELL.getValue());
        assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
        assetHistory.setTokenId(LetokenTokenTypeEnum.CAP.getId());
        assetHistory.setAmount(adminFundConfig.getFund());
        assetHistory.setSn(adminFundConfig.getId().toString());
        assetHistory.setCreateTime(LocalDateTime.now());
        assetHistory.insert();

        int updateWallet = appUserWalletService.updateUserAmountByUserIDandCoin(adminFundConfig.getFund(), new BigDecimal("0"),BigDecimal.ZERO, adminFundConfig.getUserId(), LetokenTokenTypeEnum.CAP.getId());
        if (updateWallet == 0) {
            throw new ApiServiceException(500, "mint失败，请稍后再试！");
        }
        try {
            AppUserAssetsHistory updateAssetHistory = new AppUserAssetsHistory();
            updateAssetHistory.setBalance(appUserWalletMapper.getAvailableBalance(assetHistory.getTokenId(), assetHistory.getUserId()));
            updateAssetHistory.setId(assetHistory.getId());
            assetHistory.updateById();
        }catch (Exception e){
            log.error("更新余额失败 id{} eMsg{}", assetHistory.getId(), e.getMessage());
        }


        return ApiResponse.create();
    }

    @GetMapping ("/getFundAmountByTypeCAP")
    public ApiResponse getFundAmountByType(@RequestParam("fundType") Integer fundType) {
        return ApiResponse.create(appFundInfoMapper.getFundAmountByType(WebUtils.getUserId(),fundType));
    }


    /**
     * 获取发型记录  CAP
     * @param
     * @return
     */
    @PostMapping  ("/getFundInfoListCAP")
    public ApiResponse<PageData<AppFundInfo>> getFundInfoListCAP(@Validated @RequestBody GetFundInfoList req) {
        Page<AppFundInfo> page = new Page<>(req.getPage(), req.getSize());
        Page<AppFundInfo> page1 = appFundInfoMapper.getFundInfoList(WebUtils.getUserId(),page,req.getType());
        List<AppFundInfo> appFundInfos = new ArrayList<>();
        for(AppFundInfo appFundInfo : page1.getRecords()){
            if(appFundInfo.getState().equals(2) && appFundInfo.getExpirationTime().compareTo(LocalDateTime.now()) < 0){
                continue;
            }
            appFundInfos.add(appFundInfo);
        }
        page1.setRecords(appFundInfos);
        return ApiResponse.create(PageDataUtil.getPageData(page1));
    }

    @PostMapping  ("/getmingLst")
    public ApiResponse<List<MingListRes>> getFundInfoList() {
        return ApiResponse.create(appFundInfoMapper.getMingListRes(WebUtils.getUserId()));
    }

    @PostMapping  ("/getFundDetailCAP")
    public ApiResponse<PageData<AppFundDetail>> getFundDetailCAP(@Validated @RequestBody PageReq req) {
        Page<AppFundDetail> page = new Page<>(req.getPage(), req.getSize());
        return ApiResponse.create(PageDataUtil.getPageData(appFundInfoMapper.getFundDetailCAPList(WebUtils.getUserId(),page)));
    }

    @PostMapping  ("/test")
    @NotAuthorization
    public ApiResponse test() {
        appFundInfoService.fundCapJob();
        return ApiResponse.create();
    }



}
